/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 Patrick Huy <patrick.huy@frz.cc> 
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License version 3
as published by the Free Software Foundation. You may not use, modify
or distribute this program under any other version of the
GNU Affero General Public License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package client.inventory;

import constants.GameConstants;
import java.awt.Point;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.Serializable;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import database.DatabaseConnection;
import java.util.Map;
import server.MapleItemInformationProvider;
import server.movement.AbsoluteLifeMovement;
import server.movement.LifeMovement;
import server.movement.LifeMovementFragment;

public class MaplePet implements Serializable {
    public static enum PetFlag {
       
	ITEM_PICKUP(0x01, 5190000, 5191000),
	EXPAND_PICKUP(0x02, 5190002, 5191002), //idk
	AUTO_PICKUP(0x04, 5190003, 5191003), //idk
	UNPICKABLE(0x08, 5190005, -1), //not coded
	LEFTOVER_PICKUP(0x10, 5190004, 5191004), //idk
	HP_CHARGE(0x20, 5190001, 5191001),
	MP_CHARGE(0x40, 5190006, -1),
	PET_BUFF(0x80, 5190010, -1), //idk
	PET_DRAW(0x100, 5190007, -1), //nfs
	PET_DIALOGUE(0x200, 5190008, -1); //nfs
         
	private final int i, item, remove;
	private PetFlag(int i, int item, int remove) {
	    this.i = i;
	    this.item = item;
	    this.remove = remove;
	}

	public final int getValue() {
	    return i;
	}

	public final boolean check(int flag) {
	    return (flag & i) == i;
	}
        
      
	public static final PetFlag getByAddId(final int itemId) {
	    for (PetFlag flag : PetFlag.values()) {
		if (flag.item == itemId) {
		    return flag;
		}
	    }
	    return null;
	}

	public static final PetFlag getByDelId(final int itemId) {
	    for (PetFlag flag : PetFlag.values()) {
		if (flag.remove == itemId) {
		    return flag;
		}
	    }
	    return null;
	}
    }

    private static final long serialVersionUID = 9179541993413738569L;
    private String name;
    private int Fh = 0, stance = 0, uniqueid, petitemid, secondsLeft = 0;
    private Point pos;
    private byte fullness = 100, level = 1, summoned = 0;
    private short inventorypos = 0, closeness = 0, flags = 0;    
    private boolean changed = false;
    private int skillid;
    
    private MaplePet(final int petitemid, final int uniqueid) {
        this.petitemid = petitemid;
        this.uniqueid = uniqueid;
    }

    private MaplePet(final int petitemid, final int uniqueid, final short inventorypos) {
        this.petitemid = petitemid;
        this.uniqueid = uniqueid;
        this.inventorypos = inventorypos;
    }

    public static final MaplePet loadFromDb(final int itemid, final int petid, final short inventorypos) {
        try {
            final MaplePet ret = new MaplePet(itemid, petid, inventorypos);

            Connection con = DatabaseConnection.getConnection(); // Get a connection to the database
            PreparedStatement ps = con.prepareStatement("SELECT * FROM pets WHERE petid = ?"); // Get pet details..
            ps.setInt(1, petid);

            final ResultSet rs = ps.executeQuery();
            if (!rs.next()) {
                rs.close();
                ps.close();
                return null;
            }

            ret.setName(rs.getString("name"));
            ret.setCloseness(rs.getShort("closeness"));
            ret.setLevel(rs.getByte("level"));
            ret.setFullness(rs.getByte("fullness"));
            ret.setSecondsLeft(rs.getInt("seconds"));
	    ret.setFlags(rs.getShort("flags"));
            ret.setBuffSkill(rs.getInt("skillid"));            
	    ret.changed = false;

            rs.close();
            ps.close();

            return ret;
        } catch (SQLException ex) {
            Logger.getLogger(MaplePet.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public final void saveToDb() {
	if (!changed) {
	    return;
	}
        try {
            final PreparedStatement ps = DatabaseConnection.getConnection().prepareStatement("UPDATE pets SET name = ?, level = ?, closeness = ?, fullness = ?, seconds = ?, flags = ?, skillid = ? WHERE petid = ?");
            ps.setString(1, name); // Set name
            ps.setByte(2, level); // Set Level
            ps.setShort(3, closeness); // Set Closeness
            ps.setByte(4, fullness); // Set Fullness
            ps.setInt(5, secondsLeft);
	    ps.setShort(6, flags);
            ps.setInt(7, skillid);              
            ps.setInt(8, uniqueid); // Set ID          
            ps.executeUpdate(); // Execute statement
            ps.close();
	    changed = false;
        } catch (final SQLException ex) {
            ex.printStackTrace();
        }
    }
    
      public int getBuffSkill() {
        return this.skillid;
      }

      public void setBuffSkill(int id) {
        this.skillid = id;
      }
      
      private static short getTrueFlag (int petid) {
          switch(petid) {
              case 5000000://갈색강아지
              case 5000001://갈색강아지
              case 5000002://분홍색토끼
              case 5000003://미니카고
              case 5000004://검은색고양이
              case 5000005://흰색토끼
              case 5000013://코끼리
              case 5000017://로봇
                  return 0;
              case 5000006://허스키
              case 5000007://검은색돼지
              case 5000008://팬더
              case 5000009://디노보이
              case 5000010://디노걸
              case 5000018://허스키
              case 5000022://칠면조
              case 5000023://펭귄
              case 5000026://손오공
              case 5000042://키노
              case 5000043://고슴도치
              case 5000046://키노
                  return 1;
              case 5000011://원숭이
              case 5000021://원숭이
                  return 23;
              case 5000012://아기백호
                  return 33;
              case 5000014://루돌프
              case 5000015://루돌프
                  return 17;
              case 5000020://미니예티
              case 5000024://주니어발록
                  return 55;
              case 5000040://주니어 리퍼
              case 5000064://황금돼지
              case 5000068://아기호랑이
                  return 87;
              case 5000041://꼬마눈사람
                  return 32;
              case 5000054://달팽이
                  return 101;
              case 5000065://스쿠버더키
              case 5000072://스컹크
                  return 129;
          }
          return 1;
      }
      
      public boolean isMultiPet (int petid) {
          switch(petid) {
              case 5000065:
              case 5000072:
                  return true;
              default:
                  return false;
          }
      }
      
    public static final MaplePet createPet(final int itemid, final int uniqueid) {    
        return createPet(itemid, MapleItemInformationProvider.getInstance().getName(itemid), 1, 0, 100, uniqueid, itemid == 5000054 ? 18000 : 0, getTrueFlag(itemid), 0);
    }

    public static final MaplePet createPet(int itemid, String name, int level, int closeness, int fullness, int uniqueid, int secondsLeft, short flag, int skillId) {
        if (uniqueid <= -1) { //wah
            uniqueid = MapleInventoryIdentifier.getInstance();
        }

        try { // Commit to db first
            PreparedStatement pse = DatabaseConnection.getConnection().prepareStatement("INSERT INTO pets (petid, name, level, closeness, fullness, seconds, flags, skillId) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
            pse.setInt(1, uniqueid);
            pse.setString(2, name);
            pse.setByte(3, (byte) level);
            pse.setShort(4, (short) closeness);
            pse.setByte(5, (byte) fullness);
            pse.setInt(6, secondsLeft);
	    pse.setShort(7, flag);
            pse.setInt(8, skillId);            
            pse.executeUpdate();
            pse.close();
        } catch (final SQLException ex) {
            ex.printStackTrace();
            return null;
        }
        final MaplePet pet = new MaplePet(itemid, uniqueid);
        pet.setName(name);
        pet.setLevel(level);
        pet.setFullness(fullness);
        pet.setCloseness(closeness);
	pet.setFlags(flag);
        pet.setSecondsLeft(secondsLeft);
        pet.setBuffSkill(skillId);
        return pet;
    }

    public final String getName() {
        return name;
    }

    public final void setName(final String name) {
        this.name = name;
	this.changed = true;
    }
	
	public final boolean getSummoned() {
		return summoned > 0;
	}

    public final byte getSummonedValue() {
        return summoned;
    }

    public final void setSummoned(final int summoned) {
        this.summoned = (byte)summoned;
    }

    public final short getInventoryPosition() {
        return inventorypos;
    }

    public final void setInventoryPosition(final short inventorypos) {
        this.inventorypos = inventorypos;
    }

    public int getUniqueId() {
        return uniqueid;
    }

    public final short getCloseness() {
        return closeness;
    }

    public final void setCloseness(final int closeness) {
        this.closeness = (short) closeness;
	this.changed = true;
    }

    public final byte getLevel() {
        return level;
    }

    public final void setLevel(final int level) {
        this.level = (byte) level;
	this.changed = true;
    }

    public final byte getFullness() {
        return fullness;
    }

    public final void setFullness(final int fullness) {
        this.fullness = (byte) fullness;
	this.changed = true;
    }

    public final short getFlags() {
        return flags;
    }

    public final void setFlags(final int fffh) {
        this.flags = (short) fffh;
	this.changed = true;
    }

    public final int getFh() {
        return Fh;
    }

    public final void setFh(final int Fh) {
        this.Fh = Fh;
    }

    public final Point getPos() {
        return pos;
    }

    public final void setPos(final Point pos) {
        this.pos = pos;
    }

    public final int getStance() {
        return stance;
    }

    public final void setStance(final int stance) {
        this.stance = stance;
    }

    public final int getPetItemId() {
        return petitemid;
    }
    
    
    public final boolean canConsume(final int itemId) {
        final MapleItemInformationProvider mii = MapleItemInformationProvider.getInstance();
        for (final int petId : mii.getItemEffect(itemId).getPetsCanConsume()) {
            if (petId == petitemid) {
                return true;
            }
        }
        return false;
    }

    public final void updatePosition(final List<LifeMovementFragment> movement) {
        for (final LifeMovementFragment move : movement) {
            if (move instanceof LifeMovement) {
                if (move instanceof AbsoluteLifeMovement) {
                    setPos(((LifeMovement) move).getPosition());
                }
                setStance(((LifeMovement) move).getNewstate());
            }
        }
    }

    public final int getSecondsLeft() {
        return secondsLeft;
    }

    public final void setSecondsLeft(int sl) {
        this.secondsLeft = sl;
	this.changed = true;
    }
}

